import os
import random
from entity.card import Card  # 确保Card类已经正确导入

# 读取文件并生成卡牌对象列表
def load_cards_from_file(filename):
    cards = []
    try:
        with open(filename, 'r', encoding='utf-8') as file:
            for line in file:
                # 去除行首尾空白字符
                line = line.strip()
                if line:
                    # 分割每行数据
                    data = line.split(',')
                    # 提取数据并创建卡牌对象
                    card_id = int(data[0])
                    name = data[1]
                    suit = data[2]
                    rank = data[3]
                    category = data[4]
                    # 创建卡牌对象并添加到列表
                    card = Card.create_card_from_input(card_id, name, suit, rank, category)
                    cards.append(card)
        return cards
    except FileNotFoundError:
        print(f"文件 {filename} 未找到！")
        return []
    except Exception as e:
        print(f"发生错误: {e}")
        return []
    
class Deck:
    # 静态变量：全局牌表（从文件中加载的160张卡牌）
    card_database = None

    def __init__(self, card_file=None):
        """
        初始化牌堆对象：
        - 全局牌表 card_database 只加载一次；
        - 牌堆实例从 card_database 中复制一份，然后洗牌得到随机顺序的牌堆。
        """
        if card_file is None:
            base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
            card_file = os.path.join(base_dir, 'assets', 'data', '军争160张牌.txt')
        
        # 如果全局牌表尚未加载，则加载并保存
        if Deck.card_database is None:
            Deck.card_database = load_cards_from_file(card_file)
            if len(Deck.card_database) != 160:
                print("警告：加载的牌数量不是160张！")
        
        # 从全局牌表复制一份作为当前牌堆
        self.cards = Deck.card_database.copy()
        random.shuffle(self.cards)
        
    @classmethod
    def get_card_by_id(cls, card_id):
        """
        通过卡牌 id 返回全局牌库中对应的 Card 对象。
        因为文件构造牌时卡牌顺序与 id 对应（id为1的牌在索引0），
        所以直接通过索引获取。若 card_id 超出范围则返回 None。
        """
        if cls.card_database is None:
            return None
        if 1 <= card_id <= len(cls.card_database):
            return cls.card_database[card_id - 1]
        return None
    
    def draw_top_card(self):
        """
        从牌堆顶（列表第一个元素）取出一张牌，并将其移除牌堆。
        :return: 取出的Card对象；如果牌堆为空，则返回None。
        """
        if self.cards:
            return self.cards.pop(0)
        else:
            print("牌堆已空")
            return None

    def draw_specific_card(self, target_card):
        """
        根据指定的【牌名, 花色, 点数】，从牌堆中取出离牌堆顶最近的一张符合条件的牌。
        传入的target_card应是Card对象（只需要关注name, suit, rank属性）。
        :param target_card: Card对象，用于匹配牌的牌名、花色和点数。
        :return: 符合条件的Card对象；如果没有符合条件的牌，则返回None。
        """
        for index, card in enumerate(self.cards):
            if (card.name == target_card.name and 
                card.suit == target_card.suit and 
                card.rank == target_card.rank):
                return self.cards.pop(index)
        print("未找到符合条件的牌")
        return None

    def get_suit_distribution(self):
        """
        统计当前牌堆中各花色牌的数量及占比。
        :return: 一个字典，每个键为花色，值为一个二元组：(数量, 占牌堆总数的比例)。
        """
        suit_count = {}
        total = len(self.cards)
        for card in self.cards:
            suit_count[card.suit] = suit_count.get(card.suit, 0) + 1
        
        distribution = {}
        for suit, count in suit_count.items():
            distribution[suit] = (count, count/total if total > 0 else 0)
        return distribution

    def get_rank_distribution(self):
        """
        统计当前牌堆中各点数牌的数量及占比。
        :return: 一个字典，每个键为点数（rank），值为一个二元组：(数量, 占牌堆总数的比例)。
        """
        rank_count = {}
        total = len(self.cards)
        for card in self.cards:
            rank_count[card.rank] = rank_count.get(card.rank, 0) + 1
        
        distribution = {}
        for rank, count in rank_count.items():
            distribution[rank] = (count, count/total if total > 0 else 0)
        return distribution

    def get_one_hot_state(self):
        """
        返回一个长度为160的 one-hot 列表，表示牌堆中每张牌的存在情况。
        列表索引0对应card_id=1，索引159对应card_id=160。
        1表示该卡牌仍在牌堆中，0表示已不在牌堆中。
        """
        one_hot = [0] * 160
        for card in self.cards:
            if 1 <= card.card_id <= 160:
                one_hot[card.card_id - 1] = 1
        return one_hot
    
    def draw_initial_hand(self):
        """
        抽取起始手牌：从牌堆中抽取四张牌作为起始手牌。
        如果牌堆中卡牌不足四张，则返回所有剩余牌。
        """
        initial_hand = []
        for _ in range(4):
            card = self.draw_top_card()
            if card is None:
                break
            initial_hand.append(card)
        return initial_hand

    def redraw_initial_hand(self, returned_cards):
        """
        重新抽起始手牌：
        - 将传入的四张手牌归还给牌堆；
        - 对牌堆重新洗牌；
        - 从牌堆中抽取四张新手牌作为起始手牌返回。
        """
        if len(returned_cards) != 4:
            raise ValueError("必须传入四张手牌")
        # 将归还的卡牌加入牌堆
        self.cards.extend(returned_cards)
        # 重新洗牌
        random.shuffle(self.cards)
        # 抽取新起始手牌
        return self.draw_initial_hand()
